import { BaseSystem } from '../base';
import { EVENTS, type IEventBus } from '../../events';
import type {
  SpiritualRootKey,
  SpiritualRootModel,
} from '../../model/spiritual-root';
import type { PlayerStateSystem } from '../player-state';
import { MODEL_NAME } from '../../constants/model-names';
import { FIVE_ELEMENT } from '../../constants/five-elements';
import type { SpiritualRootInfoValue } from './type';
import { CONDITION_TYPE } from '../condition-checker/type';
import type { InventoryModel } from '../../model';

export class SpiritualRootSystem extends BaseSystem {
  private bus: IEventBus;
  private playerStateSystem: PlayerStateSystem;

  constructor(bus: IEventBus, playerStateSystem: PlayerStateSystem) {
    super();
    this.bus = bus;
    this.playerStateSystem = playerStateSystem;

    this.bus.on(EVENTS.SPIRITUAL_ROOT_ADD, (key) => {
      const spiritualRootModel =
        this.playerStateSystem.getModel<SpiritualRootModel>(
          MODEL_NAME.SPIRITUAL_ROOT
        );
      spiritualRootModel.addSpiritualRootPoint(key);
    });

    this.bus.on(EVENTS.SPIRITUAL_ROOT_SUB, (key) => {
      const spiritualRootModel =
        this.playerStateSystem.getModel<SpiritualRootModel>(
          MODEL_NAME.SPIRITUAL_ROOT
        );
      spiritualRootModel.subSpiritualRootPoint(key);
    });

    this.bus.on(EVENTS.SPIRITUAL_ROOT_SUBMIT, () => {
      const spiritualRootModel =
        this.playerStateSystem.getModel<SpiritualRootModel>(
          MODEL_NAME.SPIRITUAL_ROOT
        );
      spiritualRootModel.submitSpiritualRoot();
    });

    this.bus.on(EVENTS.SPIRITUAL_ROOT_UPGRADE, (key) => {
      this.spiritualRootUpgrade(key);
    });
  }

  public getUISnapshot() {
    const spiritualRootModel =
      this.playerStateSystem.getModel<SpiritualRootModel>(
        MODEL_NAME.SPIRITUAL_ROOT
      );
    if (!spiritualRootModel || !spiritualRootModel.getConfig()) {
      return {
        config: {
          [FIVE_ELEMENT.METAL]: 0,
          [FIVE_ELEMENT.WOOD]: 0,
          [FIVE_ELEMENT.WATER]: 0,
          [FIVE_ELEMENT.FIRE]: 0,
          [FIVE_ELEMENT.EARTH]: 0,
        },
        tempConfig: {
          [FIVE_ELEMENT.METAL]: 0,
          [FIVE_ELEMENT.WOOD]: 0,
          [FIVE_ELEMENT.WATER]: 0,
          [FIVE_ELEMENT.FIRE]: 0,
          [FIVE_ELEMENT.EARTH]: 0,
        },
        skillPoints: 0,
        tempSkillPoints: 0,
        spiritualRootInfo: {} as Record<
          SpiritualRootKey,
          SpiritualRootInfoValue
        >,
      };
    }

    const config = spiritualRootModel.getConfig();

    const spiritualRootInfo = Object.keys(config).reduce((acc, key) => {
      const objKey = key as SpiritualRootKey;
      const value = config[objKey];
      const upgradeConditions =
        spiritualRootModel.getSpiritualRootLevelCondition(objKey);
      const upgradeConditionProgress =
        this.playerStateSystem.getConditionsProgress(upgradeConditions);
      const canUpgrade =
        upgradeConditions.length > 0 &&
        this.playerStateSystem.checkConditions(upgradeConditions);
      acc[key as SpiritualRootKey] = {
        level: value,
        levelName: spiritualRootModel.getSpiritualRootLevelName(value),
        upgradeConditionProgress,
        canUpgrade,
      };
      return acc;
    }, {} as Record<SpiritualRootKey, SpiritualRootInfoValue>);

    return {
      config: spiritualRootModel.getConfig(),
      tempConfig: spiritualRootModel.getTempConfig(),
      skillPoints: spiritualRootModel.getSkillPoints(),
      tempSkillPoints: spiritualRootModel.getTempSkillPoints(),
      spiritualRootInfo,
    };
  }

  private spiritualRootUpgrade(key: SpiritualRootKey) {
    const spiritualRootModel =
      this.playerStateSystem.getModel<SpiritualRootModel>(
        MODEL_NAME.SPIRITUAL_ROOT
      );
    const inventoryModel = this.playerStateSystem.getModel<InventoryModel>(
      MODEL_NAME.INVENTORY
    );
    if (!spiritualRootModel || !inventoryModel) return;
    const upgradeConditions =
      spiritualRootModel.getSpiritualRootLevelCondition(key);
    const canUpgrade =
      upgradeConditions.length > 0 &&
      this.playerStateSystem.checkConditions(upgradeConditions);
    if (!canUpgrade) return;
    upgradeConditions.forEach((condition) => {
      switch (condition.type) {
        case CONDITION_TYPE.ITEM:
          const itemId = condition.itemId;
          const needCount = condition.count;
          spiritualRootModel.upgradeSpiritualRoot(key);
          inventoryModel.removeItemByItemId(itemId, needCount);
          break;
        default:
          throw new Error('不支持的条件类型');
      }
    });
    this.bus.emit(EVENTS.SPIRITUAL_ROOT_UPGRADE_COMPLETED);
  }
}
